import { reactive } from 'vue'
import { eachTree, treeMap, filter } from '@/utils/tree'
import { FormSchema } from '@/components/Form'
import { TableColumn } from '@/components/Table'
import { DescriptionsSchema } from '@/components/Descriptions'
import { h } from 'vue'
import { ElTooltip, ElIcon } from 'element-plus'
import { QuestionFilled } from '@element-plus/icons-vue'
import { getFormTip } from '@/utils/tips'

export type CrudSchema = Omit<TableColumn, 'children'> & {
  search?: CrudSearchParams
  table?: CrudTableParams
  form?: CrudFormParams
  detail?: CrudDescriptionsParams
  children?: CrudSchema[]
  // 新增提示配置
  showTip?: boolean
  tipConfig?: {
    formType?: string
    customTip?: string
  }
}

interface CrudSearchParams extends Omit<FormSchema, 'field'> {
  hidden?: boolean
}

interface CrudTableParams extends Omit<TableColumn, 'field'> {
  hidden?: boolean
}

interface CrudFormParams extends Omit<FormSchema, 'field'> {
  hidden?: boolean
}

interface CrudDescriptionsParams extends Omit<DescriptionsSchema, 'field'> {
  hidden?: boolean
}

interface AllSchemas {
  searchSchema: FormSchema[]
  tableColumns: TableColumn[]
  formSchema: FormSchema[]
  detailSchema: DescriptionsSchema[]
}

// 新增选项接口
interface UseCrudSchemasOptions {
  showTips?: boolean
  defaultFormType?: string
}

/**
 * @deprecated 不推荐使用，感觉过于繁琐，不是很灵活 可能会在某个版本中删除
 */
export const useCrudSchemas = (
  crudSchema: CrudSchema[],
  options: UseCrudSchemasOptions = {}
) => {
  const { showTips = false, defaultFormType = 'preferredCatalog' } = options

  const allSchemas = reactive<AllSchemas>({
    searchSchema: [],
    tableColumns: [],
    formSchema: [],
    detailSchema: []
  })

  // 初始化
  const init = async () => {
    const searchSchema = filterSearchSchema(crudSchema)
    // @ts-ignore
    allSchemas.searchSchema = searchSchema || []

    const tableColumns = filterTableSchema(crudSchema)
    allSchemas.tableColumns = tableColumns || []

    const formSchema = await filterFormSchema(crudSchema, showTips, defaultFormType)
    allSchemas.formSchema = formSchema

    const detailSchema = filterDescriptionsSchema(crudSchema)
    allSchemas.detailSchema = detailSchema
  }

  // 立即执行初始化
  init()

  return {
    allSchemas
  }
}

// 过滤 Search 结构
const filterSearchSchema = (crudSchema: CrudSchema[]): FormSchema[] => {
  const searchSchema: FormSchema[] = []
  const length = crudSchema.length

  for (let i = 0; i < length; i++) {
    const schemaItem = crudSchema[i]
    if (schemaItem.search?.hidden === true) {
      continue
    }
    const searchSchemaItem = {
      component: schemaItem?.search?.component || 'Input',
      ...schemaItem.search,
      field: schemaItem.field,
      label: schemaItem.search?.label || schemaItem.label
    }

    searchSchema.push(searchSchemaItem)
  }

  return searchSchema
}

// 过滤 table 结构
const filterTableSchema = (crudSchema: CrudSchema[]): TableColumn[] => {
  const tableColumns = treeMap<CrudSchema>(crudSchema, {
    conversion: (schema: CrudSchema) => {
      if (!schema?.table?.hidden) {
        return {
          ...schema,
          ...schema.table
        }
      }
    }
  })

  return filter<TableColumn>(tableColumns as TableColumn[], (data) => {
    if (data.children === void 0) {
      delete data.children
    }
    return !!data.field
  })
}

// 在 useCrudSchemas.ts 中修改
const filterFormSchema = async (
  crudSchema: CrudSchema[],
  showTips: boolean,
  defaultFormType: string
): Promise<FormSchema[]> => {
  const formSchema: FormSchema[] = []
  const length = crudSchema.length

  // 预加载所有提示信息
  const tipPromises: Promise<{field: string, tip: string}>[] = []

  if (showTips) {
    for (let i = 0; i < length; i++) {
      const formItem = crudSchema[i]
      if (formItem.form?.hidden === true || !formItem.showTip) {
        continue
      }

      tipPromises.push(
        getFormTip(
          formItem.tipConfig?.formType || defaultFormType,
          formItem.field
        ).then(tip => ({
          field: formItem.field,
          tip: tip || formItem.label
        }))
      )
    }
  }

  // 等待所有提示信息加载完成
  const tipResults = await Promise.all(tipPromises)
  const tipMap = new Map(tipResults.map(result => [result.field, result.tip]))

  for (let i = 0; i < length; i++) {
    const formItem = crudSchema[i]

    if (formItem.form?.hidden === true) {
      continue
    }

    const formSchemaItem: FormSchema = {
      component: formItem?.form?.component || 'Input',
      ...formItem.form,
      field: formItem.field,
      label: formItem.form?.label || formItem.label
    }

    if (showTips && formItem.showTip) {
      const tipContent = tipMap.get(formItem.field) || formItem.label

      formSchemaItem.formItemProps = {
        ...formSchemaItem.formItemProps,
        slots: {
          ...formSchemaItem.formItemProps?.slots,
          label: () =>
            h('span', {
              style: 'display: inline-flex; align-items: center; gap: 4px;'
            }, [
              formItem.form?.label || formItem.label,
              h(ElTooltip, {
                content: tipContent,
                placement: 'top',
                popperStyle: {
                  maxWidth: '400px',
                  minWidth: '200px',
                  wordBreak: 'break-word',
                  whiteSpace: 'normal',
                  lineHeight: '1.5',
                  padding: '12px',
                  fontSize: '14px',
                  textAlign: 'left'
                },
                showAfter: 200,
                hideAfter: 0
              }, {
                default: () => h(ElIcon, {
                  style: 'color: #909399; cursor: help; font-size: 14px;'
                }, () => h(QuestionFilled))
              })
            ])
        }
      }
    }

    formSchema.push(formSchemaItem)
  }

  return formSchema
}

// 过滤 descriptions 结构
const filterDescriptionsSchema = (crudSchema: CrudSchema[]): DescriptionsSchema[] => {
  const descriptionsSchema: FormSchema[] = []

  eachTree(crudSchema, (schemaItem: CrudSchema) => {
    if (!schemaItem?.detail?.hidden) {
      const descriptionsSchemaItem = {
        ...schemaItem.detail,
        field: schemaItem.field,
        label: schemaItem.detail?.label || schemaItem.label
      }

      delete descriptionsSchemaItem.hidden

      descriptionsSchema.push(descriptionsSchemaItem)
    }
  })

  return descriptionsSchema
}
